pub mod tools;
use crate::{mail_list, media};
use crate::push_message;
use crate::customer;
use serde::Deserialize;
use serde::Serialize;

#[derive(Debug)]
pub struct Agent{
    pub id:u32,
    corpid:String,
    agent_secret:String,
    access_token:String,
    invalid_time:u64,
}



#[derive(Debug,Serialize,Deserialize)]
struct WxResponse{
    errcode:u32,
    errmsg:String,
}

impl Agent{

    ///构建一个agent对象
    pub fn new(id:u32,corpid:String,agent_secret:String)->Self{
        Agent{
            id,
            corpid,
            agent_secret,
            access_token:String::from(""),
            invalid_time:0u64,
        }
    }


    pub fn get_access_token(&self)->&str{
        &self.access_token
    }

    /*
    判断是否需要刷新token
     */
    /// 刷新token
    /// # 提示
    /// 不是每次都请求微信接口，只有当access_token为""时，或有效时间过了，才会请求
    pub fn fresh_token(&mut self)->&Self{
        let now_second=tools::get_current_second();
        if 0==self.access_token.trim().len() || self.invalid_time<=now_second{//如果token已经失效
            let result=self.get_token();
            match result {
                Ok(r)=>{
                    if 0==r["errcode"].as_u64().unwrap() {
                        self.access_token=r["access_token"].as_str().unwrap().to_string();
                        self.invalid_time=tools::get_current_second()+r["expires_in"].as_u64().unwrap();
                    }else {
                        panic!("{}",&r["errmsg"])
                    }
                },
                Err(err)=>{
                    panic!("{:?}",err)
                }
            }
        }
        return self;
    }

    /*
      gettoken
      根据corpid和应用secret获取access_token
     */
    ///根据corpid和应用secret获取access_token
    /// # 接口地址
    ///https://qyapi.weixin.qq.com/cgi-bin/gettoken
    fn get_token(&mut self)->Result<serde_json::Value, reqwest::Error>{
        let url = format!(
            "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={}&corpsecret={}",
            &self.corpid, &self.agent_secret
        );
        tools::get_json(url)
    }


    /*
      获取通讯录中用户服务对象
     */
    ///获取通讯录中用户服务对象
    /// # 提示
    /// 该方法会新建一个agent给userservice，这样会导致access_token在各个服务对像中不一至。
    /// 虽然有点不严谨，不过影响不大，要怪只能怪rust对开发设计不太友好，只注重语言设计
    /// 而真正的rust风格中继承都是采用组合的方式实现的，这样agent的所有权会转移到user_service中，
    /// # rust继承做法
    /// ```
    /// use weixin_rust::agent;
    /// use weixin_rust::agent::Agent;
    /// use weixin_rust::mail_list::user::UserService;
    ///
    /// let mut agent=Agent::new{corpid:"".to_string(),agent_secret:"".to_string()};
    /// let mut user_service=UserService{agent};//注意agent所有权转移了哦
    ///
    /// user_service.agent.get_user_info("code...");//后面只能这样操作喽
    /// ```
    pub fn get_user_service(&self)->mail_list::user::UserService{
        mail_list::user::UserService{agent:Agent{
            id:self.id,
            corpid:String::from(&self.corpid),
            agent_secret:String::from(&self.agent_secret),
            access_token:String::from(&self.access_token),
            invalid_time:self.invalid_time,
        }}
    }

    /*
      获取通讯录中部门服务对象
     */
    ///获取通讯录中部门服务对象
    /// # 提示
    /// 该方法会新建一个agent给deptservice，这样会导致access_token在各个服务对像中不一至。
    /// 虽然有点不严谨，不过影响不大，要怪只能怪rust对开发设计不太友好，只注重语言设计
    /// 而真正的rust风格中继承都是采用组合的方式实现的，这样agent的所有权会转移到user_service中，
    /// # rust继承做法
    /// ```
    /// use weixin_rust::agent;
    /// use weixin_rust::agent::Agent;
    /// use weixin_rust::mail_list::dept::DeptService;
    ///
    /// let mut agent=Agent::new{corpid:"".to_string(),agent_secret:"".to_string()};
    /// let mut dept_service=DeptService{agent};//注意agent所有权转移了哦
    /// dept_service.agent.get_user_info("code...");//后面只能这样操作喽
    /// ```
    pub fn get_dept_service(&self)->mail_list::dept::DeptService{
        mail_list::dept::DeptService{agent:Agent{
            id:self.id,
            corpid:String::from(&self.corpid),
            agent_secret:String::from(&self.agent_secret),
            access_token:String::from(&self.access_token),
            invalid_time:self.invalid_time,
        }}
    }

    /*
      获取通讯录中标签服务对象
     */
    ///获取通讯录中标签服务对象
    /// # 提示
    /// 该方法会新建一个agent给tagservice，这样会导致access_token在各个服务对像中不一至。
    /// 虽然有点不严谨，不过影响不大，要怪只能怪rust对开发设计不太友好，只注重语言设计
    /// 而真正的rust风格中继承都是采用组合的方式实现的，这样agent的所有权会转移到user_service中，
    /// # rust继承做法
    /// ```
    /// use weixin_rust::agent;
    /// use weixin_rust::agent::Agent;
    /// use weixin_rust::mail_list::tag::TagService;
    ///
    /// let mut agent=Agent::new{corpid:"".to_string(),agent_secret:"".to_string()};
    /// let mut tag_service=TagService{agent};//注意agent所有权转移了哦
    ///
    /// tag_service.agent.get_user_info("code...");//后面只能这样操作喽
    /// ```
    pub fn get_tag_service(&self)->mail_list::tag::TagService{
        mail_list::tag::TagService{agent:Agent{
            id:self.id,
            corpid:String::from(&self.corpid),
            agent_secret:String::from(&self.agent_secret),
            access_token:String::from(&self.access_token),
            invalid_time:self.invalid_time,
        }}
    }

    /*
      获取通讯录中异步服务对象
     */
    ///获取通讯录中异步服务对象
    /// # 提示
    /// 该方法会新建一个agent给syncservice，这样会导致access_token在各个服务对像中不一至。
    /// 虽然有点不严谨，不过影响不大，要怪只能怪rust对开发设计不太友好，只注重语言设计
    /// 而真正的rust风格中继承都是采用组合的方式实现的，这样agent的所有权会转移到user_service中，
    /// # rust继承做法
    /// ```
    /// use weixin_rust::agent;
    /// use weixin_rust::agent::Agent;
    /// use weixin_rust::mail_list::sync::SyncService;
    ///
    /// let mut agent=Agent::new{corpid:"".to_string(),agent_secret:"".to_string()};
    /// let mut sync_service=SyncService{agent};//注意agent所有权转移了哦
    ///
    /// sync_service.agent.get_user_info("code...");//后面只能这样操作喽
    /// ```
    pub fn get_sync_service(&self)->mail_list::sync::SyncService{
        mail_list::sync::SyncService{agent:Agent{
            id:self.id,
            corpid:String::from(&self.corpid),
            agent_secret:String::from(&self.agent_secret),
            access_token:String::from(&self.access_token),
            invalid_time:self.invalid_time,
        }}
    }

    /*
      获取通讯录中标签服务对象
     */
    ///获取通讯录中消息服务对象
    /// # 提示
    /// 该方法会新建一个agent给messageservice，这样会导致access_token在各个服务对像中不一至。
    /// 虽然有点不严谨，不过影响不大，要怪只能怪rust对开发设计不太友好，只注重语言设计
    /// 而真正的rust风格中继承都是采用组合的方式实现的，这样agent的所有权会转移到user_service中，
    /// # rust继承做法
    /// ```
    /// use weixin_rust::agent;
    /// use weixin_rust::agent::Agent;
    /// use weixin_rust::push_message::MessageService;
    ///
    /// let mut agent=Agent::new{corpid:"".to_string(),agent_secret:"".to_string()};
    /// let mut msg_service=MessageService{agent};//注意agent所有权转移了哦
    ///
    /// msg_service.agent.get_user_info("code...");//后面只能这样操作喽
    /// ```
    pub fn get_message_service(&self)->push_message::MessageService{
        push_message::MessageService{agent:Agent{
            id:self.id,
            corpid:String::from(&self.corpid),
            agent_secret:String::from(&self.agent_secret),
            access_token:String::from(&self.access_token),
            invalid_time:self.invalid_time,
        }}
    }

    /*
      获取通讯录中标签服务对象
     */
    ///获取通讯录中客户服务对象
    /// # 提示
    /// 该方法会新建一个agent给customerservice，这样会导致access_token在各个服务对像中不一至。
    /// 虽然有点不严谨，不过影响不大，要怪只能怪rust对开发设计不太友好，只注重语言设计
    /// 而真正的rust风格中继承都是采用组合的方式实现的，这样agent的所有权会转移到user_service中，
    /// # rust继承做法
    /// ```
    /// use weixin_rust::agent;
    /// use weixin_rust::agent::Agent;
    /// use weixin_rust::customer::CustomService;
    ///
    /// let mut agent=Agent::new{corpid:"".to_string(),agent_secret:"".to_string()};
    /// let mut cus_service=CustomService{agent};//注意agent所有权转移了哦
    ///
    /// cus_service.agent.get_user_info("code...");//后面只能这样操作喽
    ///
    /// ```
    pub fn get_customer_service(&self)->customer::CustomerService{
        customer::CustomerService{agent:Agent{
            id:self.id,
            corpid:String::from(&self.corpid),
            agent_secret:String::from(&self.agent_secret),
            access_token:String::from(&self.access_token),
            invalid_time:self.invalid_time,
        }}
    }


    ///获取媒体上传服务对象
    /// # 提示
    /// 该方法会新建一个agent给mediaservice，这样会导致access_token在各个服务对像中不一至。
    /// 虽然有点不严谨，不过影响不大，要怪只能怪rust对开发设计不太友好，只注重语言设计
    /// 而真正的rust风格中继承都是采用组合的方式实现的，这样agent的所有权会转移到user_service中，
    /// # rust继承做法
    /// ```
    /// use weixin_rust::agent;
    /// use weixin_rust::agent::Agent;
    /// use weixin_rust::media::MediaService;
    ///
    /// let mut agent=Agent::new{corpid:"".to_string(),agent_secret:"".to_string()};
    /// let mut media_service=MediaService{agent};//注意agent所有权转移了哦
    ///
    /// media_service.agent.get_user_info("code...");//后面只能这样操作喽
    /// ```
    pub fn get_media_service(&self)->media::MediaService{
        media::MediaService{agent:Agent{
            id:self.id,
            corpid:String::from(&self.corpid),
            agent_secret:String::from(&self.agent_secret),
            access_token:String::from(&self.access_token),
            invalid_time:self.invalid_time,
        }}
    }


    /*
       获取访问用户身份
       #url
       https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo
     */
    /// 获取访问用户身份
    /// # 微信接口
    /// https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo
    pub fn get_user_info(&mut self,code:&str)->Result<serde_json::Value, reqwest::Error>{
        self.fresh_token();
        let url=format!("https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token={}&code={}",self.get_access_token(),code);
        tools::get_json(url)
    }

    /*
       获取访问用户敏感信息
       #url
       https://qyapi.weixin.qq.com/cgi-bin/auth/getuserdetail
     */
    /// 获取访问用户敏感信息
    /// # 微信接口
    /// https://qyapi.weixin.qq.com/cgi-bin/auth/getuserdetail
    pub fn get_user_detail(&mut self,json_params:&str)->Result<serde_json::Value, reqwest::Error>{
        self.fresh_token();
        let url=format!("https://qyapi.weixin.qq.com/cgi-bin/auth/getuserdetail?access_token={}",self.get_access_token());
        tools::post_json(url,Some(String::from(json_params)))
    }


    /*
    get_api_domain_ip
    获取企业微信API域名IP段
    */
    /// 获取企业微信API域名IP段
    /// # 微信接口
    /// https://qyapi.weixin.qq.com/cgi-bin/get_api_domain_ip
    pub fn get_api_domain_ip(&mut self)-> Result<serde_json::Value, reqwest::Error>{
        self.fresh_token();
        let url=format!("https://qyapi.weixin.qq.com/cgi-bin/get_api_domain_ip?access_token={}",self.access_token);
        tools::get_json(url)
    }

    /*
     openuserid_to_userid
     将代开发应用或第三方应用获取的密文open_userid转换为明文userid。
    */
    /// 将代开发应用或第三方应用获取的密文open_userid转换为明文userid
    /// # 微信接口
    /// https://qyapi.weixin.qq.com/cgi-bin/batch/openuserid_to_userid
    pub fn openuserid_to_userid(&mut self,json_params:&str)->Result<serde_json::Value, reqwest::Error>{
        self.fresh_token();
        let url=format!("https://qyapi.weixin.qq.com/cgi-bin/batch/openuserid_to_userid?access_token={}",self.access_token);
        tools::post_json(url,Some(String::from(json_params)))
    }

    /*
     convert_tmp_external_userid
     tmp_external_userid的转换
    */
    /// tmp_external_userid的转换
    /// # 微信接口
    /// https://qyapi.weixin.qq.com/cgi-bin/idconvert/convert_tmp_external_userid
    pub fn convert_tmp_external_userid(&mut self,json_params:&str)->Result<serde_json::Value, reqwest::Error>{
        self.fresh_token();
        let url=format!("https://qyapi.weixin.qq.com/cgi-bin/idconvert/convert_tmp_external_userid?access_token={}",self.access_token);
        tools::post_json(url,Some(String::from(json_params)))
    }

    /*
     get_perm_list
     获取应用的可见范围
    */
    ///获取应用的可见范围
    /// # 接口地址
    ///https://qyapi.weixin.qq.com/cgi-bin/linkedcorp/agent/get_perm_list
    pub fn get_perm_list(&mut self)->Result<serde_json::Value, reqwest::Error>{
        self.fresh_token();
        let url=format!("https://qyapi.weixin.qq.com/cgi-bin/linkedcorp/agent/get_perm_list?access_token={}",self.access_token);
        tools::post_json(url,None)
    }

    /*
     linkedcorp/user/get
     获取互联企业成员详细信息
    */
    /// 获取互联企业成员详细信息
    /// # 微信接口
    /// https://qyapi.weixin.qq.com/cgi-bin/linkedcorp/user/get
    pub fn get_agent_user(&mut self,json_params:&str)->Result<serde_json::Value, reqwest::Error>{
        self.fresh_token();
        let url=format!("https://qyapi.weixin.qq.com/cgi-bin/linkedcorp/user/get?access_token={}",self.access_token);
        tools::post_json(url,Some(String::from(json_params)))
    }

    /*
     linkedcorp/user/simplelist
     获取互联企业部门成员
    */
    /// 获取互联企业部门成员
    /// # 微信接口
    /// https://qyapi.weixin.qq.com/cgi-bin/linkedcorp/user/simplelist
    pub fn get_agent_simplelist(&mut self,json_params:&str)->Result<serde_json::Value, reqwest::Error>{
        self.fresh_token();
        let url=format!("https://qyapi.weixin.qq.com/cgi-bin/linkedcorp/user/simplelist?access_token={}",self.access_token);
        tools::post_json(url,Some(String::from(json_params)))
    }

    /*
     linkedcorp/user/list
     获取互联企业部门成员详情
    */
    /// 获取互联企业部门成员详情
    /// # 微信接口
    /// https://qyapi.weixin.qq.com/cgi-bin/linkedcorp/user/list
    pub fn list_agent_user(&mut self,json_params:&str)->Result<serde_json::Value, reqwest::Error>{
        self.fresh_token();
        let url=format!("https://qyapi.weixin.qq.com/cgi-bin/linkedcorp/user/list?access_token={}",self.access_token);
        tools::post_json(url,Some(String::from(json_params)))
    }

    /*
     linkedcorp/user/list
     获取互联企业部门列表
     # address
     https://qyapi.weixin.qq.com/cgi-bin/linkedcorp/department/list
    */
    /// 获取互联企业部门列表
    /// # 微信接口
    /// https://qyapi.weixin.qq.com/cgi-bin/linkedcorp/department/list
    pub fn list_agent_dept(&mut self,json_params:&str)->Result<serde_json::Value, reqwest::Error>{
        self.fresh_token();
        let url=format!("https://qyapi.weixin.qq.com/cgi-bin/linkedcorp/department/list?access_token={}",self.access_token);
        tools::post_json(url,Some(String::from(json_params)))
    }

    /*
      获取上下游信息
     */
    /// 获取上下游信息
    /// # 微信接口
    /// https://qyapi.weixin.qq.com/cgi-bin/corpgroup/corp/get_chain_list
    pub fn get_chain_list(&mut self)-> Result<serde_json::Value, reqwest::Error>{
        self.fresh_token();
        let url=format!("https://qyapi.weixin.qq.com/cgi-bin/corpgroup/corp/get_chain_list?access_token={}",self.access_token);
        tools::get_json(url)
    }

    /*
      获取指定的应用详情
      #url
      https://qyapi.weixin.qq.com/cgi-bin/agent/get
     */
    /// 获取指定的应用详情
    /// # 微信接口
    /// https://qyapi.weixin.qq.com/cgi-bin/agent/get
    pub fn get_agent(&mut self,agentid:&str)-> Result<serde_json::Value, reqwest::Error>{
        self.fresh_token();
        let url=format!("https://qyapi.weixin.qq.com/cgi-bin/agent/get?access_token={}&agentid={}",self.access_token,agentid);
        tools::get_json(url)
    }

    /*
     设置应用
     #url
     https://qyapi.weixin.qq.com/cgi-bin/agent/set
     */
    /// 设置应用
    /// # 微信接口
    /// https://qyapi.weixin.qq.com/cgi-bin/agent/set
    pub fn setup_agent(&mut self,json_params:&str)->Result<serde_json::Value, reqwest::Error>{
        self.fresh_token();
        let url=format!("https://qyapi.weixin.qq.com/cgi-bin/agent/set?access_token={}",self.access_token);
        tools::post_json(url,Some(String::from(json_params)))
    }

    /*
     设置应用在工作台展示的模版
     #url
     https://qyapi.weixin.qq.com/cgi-bin/agent/set_workbench_template
     */
    /// 设置应用在工作台展示的模版
    /// # 微信接口
    /// https://qyapi.weixin.qq.com/cgi-bin/agent/set_workbench_template
    pub fn set_workbench_template(&mut self,json_params:&str)->Result<serde_json::Value, reqwest::Error>{
        self.fresh_token();
        let url=format!("https://qyapi.weixin.qq.com/cgi-bin/agent/set_workbench_template?access_token={}",self.access_token);
        tools::post_json(url,Some(String::from(json_params)))
    }

    /*
     创建菜单
     #url
     https://qyapi.weixin.qq.com/cgi-bin/menu/create
     */
    /// 创建菜单
    /// # 微信接口
    /// https://qyapi.weixin.qq.com/cgi-bin/menu/create
    pub fn create_menu(&mut self,json_params:&str)->Result<serde_json::Value, reqwest::Error>{
        self.fresh_token();
        let url=format!("https://qyapi.weixin.qq.com/cgi-bin/menu/create?access_token={}",self.access_token);
        tools::post_json(url,Some(String::from(json_params)))
    }

    /*
     获取菜单
     #url
     https://qyapi.weixin.qq.com/cgi-bin/menu/get
     */
    /// 获取菜单
    /// # 微信接口
    /// https://qyapi.weixin.qq.com/cgi-bin/menu/get
    pub fn get_menu(&mut self,agentid:&str)->Result<serde_json::Value, reqwest::Error>{
        self.fresh_token();
        let url=format!("https://qyapi.weixin.qq.com/cgi-bin/menu/get?access_token={}&agentid={}",self.access_token,agentid);
        tools::get_json(url)
    }

    /*
     删除菜单
     #url
     https://qyapi.weixin.qq.com/cgi-bin/menu/get
     */
    /// 删除菜单
    /// # 微信接口
    ///  https://qyapi.weixin.qq.com/cgi-bin/menu/get
    pub fn delete_menu(&mut self,agentid:&str)->Result<serde_json::Value, reqwest::Error>{
        self.fresh_token();
        let url=format!("https://qyapi.weixin.qq.com/cgi-bin/menu/delete?access_token={}&agentid={}",self.access_token,agentid);
        tools::get_json(url)
    }



}